权限

数据库角色

PostgreSQL 使用角色的概念管理数据库访问权限。

一个角色可以被看成是一个数据库用户或者是一个数据库用户组,这取决于角色被怎样设置。

创建角色

sql
1CREATE ROLE name;
2-- 例子
3CREATE ROLE user1;

移除角色

sql
1DROP ROLE name;
2-- 例子
3DROP ROLE user1;

查询角色

sql
1SELECT rolname FROM pg_roles;

创建的角色会在 pg_roles 系统表中查到。

刚初始化好的系统有一个预定义的超级用户 postgres。

必须以初始角色的身份连接才能创建更多的角色。

每一个到数据库服务器的连接都是使用某个特定角色名建立的,并且这个角色决定发起连接的命令的初始访问权限。

角色属性

一个数据库角色可以有一些属性,它们定义角色的权限并且与客户端认证系统交互。

  • login privilege 只有具有LOGIN属性的角色登录数据库。

    使用以下命令能够创建一个角色并拥有登录的权限:

    sql
    1CREATE ROLE name LOGIN;
    2CREATE USER name;

    CREATE USERCREATE ROLE等效,但CREATE USER默认设置LOGIN,而CREATE ROLE不 行)。

    如果已经有了角色就是用 ALTER ROLE 修改权限。

    sql
    1ALTER ROLE name LOGIN;
  • superuser status 除了登录外绕开所有权限检查的超级用户权限

    要创建一个新数据库超级用户,需要一个超级用户使用以下命令给予权限

    sql
    1-- 增加权限
    2CREATE ROLE name SUPERUSER
    3-- 修改权限
    4ALTER ROLE name SUPERUSER
  • database creation 创建数据库的权限

    除了超级用户,一个角色必须被显式给予权限才能创建数据库。

    sql
    1CREATE ROLE name CREATEDB
    2ALTER ROLE name CREATEDB
  • role creation 创建更多角色的权限

    除了超级用户,一个角色必须被显式给予权限才能创建更多角色。

    sql
    1CREATE ROLE name CREATEROLE
    2ALTER ROLE name CREATEROLE

    一个带有CREATEROLE权限的角色也可以修改和删除其他角色,还可以授予或回收角色中的成员关系。然而,要创建、修改、删除或修改一个超级用户角色的成员关系,需要以超级用户的身份操作。CREATEROLE不足以完成这一切。

  • initiating replication

    除了超级用户,角色必须被赋予流复制(复制整个数据库)的权限。一个被用于流复制的角色必须也具有LOGIN权限。

    sql
    1CREATE ROLE name REPLICATION LOGIN
    2ALTER ROLE name REPLICATION LOGIN
  • password 指定登录密码

    sql
    1CREATE ROLE name PASSWORD 'string'
    2ALTER ROLE name PASSWORD 'string'

最好单独创建具有创建权限和创建数据库权限的角色而不是创建更多超级用户。这种方法避免了在非必要情况下作为超级用户操作任务的风险。

分配权限

一旦一个对象(表、函数等)被创建,它会被分配一个 owner。owner 通常是执行创建语句的角色。

对于大部分类型的对象,初始状态下只有所有者(或者超级用户)能够对该对象做任何事情。

现在我们已经知道如何创建角色了,但是为了允许角色能够使用其他用户创建的表,还需要分配权限。

有多种不同的权限:SELECTINSERTUPDATEDELETETRUNCATEREFERENCESTRIGGERCREATECONNECTTEMPORARYEXECUTE以及USAGE

通常修改或者删除一个对象的权力只有对象的所有者才有。

但可以重新分配所有者,例如分配一个 table 的 owner:

sql
1ALTER TABLE table_name OWNER TO new_owner;

一般只有对象的当前所有者或者超级用户才能够这样分配。

要分配权限,可以使用GRANT命令:

sql
1GRANT UPDATE ON accounts TO joe;

上面是将 accounts 表的 update 权限分配给叫 joe 的角色。

ALL取代特定权限会把与对象类型相关的所有权限全部授权。

sql
1-- 把 accounts 表的所有权限都分配给 joe。
2GRANT ALL ON accounts TO joe;
3-- 把所有 table 的 select 权限分配给 admin
4GRANT SELECT ON ALL TABLES IN SCHEMA public TO admin;

如果我想给每一个角色授予一个权限,用默认的 PUBLIC 替代:

sql
1-- 让每个角色都有 orders 表的查询权限
2GRANT SELECT ON orders TO "public";

如果想要撤销一个角色的权限,使用REVOKE

sql
1-- 撤销每个角色的 orders 表查询权限
2REVOKE SELECT ON orders FROM "public";

对象拥有者的特殊权限(即执行DROPGRANTREVOKE等的权力)总是隐式地属于拥有者,并且不能被授予或撤销。

但是对象拥有者可以选择撤销他们自己的普通权限,例如把一个表变得对他们自己和其他人只读。

一般情况下,只有对象拥有者(或者超级用户)可以授予或撤销一个对象上的权限。但是可以在授予权限时使用“with grant option”来允许接收人将权限转授给其他人。如果后来授予选项被撤销,则所有从接收人那里获得的权限(直接或者通过授权链获得)都将被撤销。

重点摘录自官方中文文档中关于权限的详细说明

角色成员关系

把用户分组在一起来便于管理权限常常很方便:那样,权限可以被授予一整个组或从一整个组回收。

创建一个组角色:

sql
1CREATE ROLE name;

通常被用作一个组的角色不需要有LOGIN属性,但也可以设置它。

当组角色存在后,就可以使用GRANT或者REVOKE命令增加或者移除成员:

sql
1GRANT group_role TO role1, ... ;
2REVOKE group_role FROM role1, ... ;

还可以为其他组成员授予成员关系,因为组角色和非组角色之间其实没有任何区别。

组角色的成员可以以两种方式使用角色的权限。

  1. 一个组的每一个成员可以显式地用SET ROLE来临时“成为”组角色。
  2. INHERIT属性的成员角色自动地具有它们所属角色的权限,包括任何组角色继承得到的权限。

以下为一个例子:

sql
1CREATE ROLE joe LOGIN INHERIT;
2CREATE ROLE admin NOINHERIT;
3CREATE ROLE wheel NOINHERIT;
4GRANT admin TO joe;
5GRANT wheel TO admin;

上面的 sql 创建了三个成员:joe、admin 和 wheel,其中只有 joe 具有 INHERIT 属性。

admin 的权限分配给了 joe。

wheel 的权限分配给了 admin。

当 joe 登录后,它会拥有 LOGIN 的权限,并且还继承了授予 admin 的权限。

然而,wheel 的权限,joe 是不能用的,因为 admin 带的属性为 NOINHERIT,所以 admin 没有将 wheel 的权限带给间接成员 joe。

当执行:

sql
1SET ROLE admin;

后,可以临时成为 admin ,只时候只有 admin 的权限而没有 joe 的权限。

在执行:

sql
1SET ROLE wheel;

后,该会话将只拥有授予给wheel的权限,但是没有授予给joeadmin的权限。

如果想恢复权限状态(选其一):

sql
1SET ROLE joe;
2SET ROLE NONE;
3RESET ROLE;

角色属性LOGINSUPERUSERCREATEDBCREATEROLE可以被认为是一种特殊权限,但是它们从来不会像数据库对象上的普通权限那样被继承。

要使用这些属性,你必须实际SET ROLE到一个有这些属性之一的特定角色。继续上述例子,我们可以选择授予CREATEDBCREATEROLEadmin角色。然后一个以joe角色连接的会话将不会立即有这些权限,只有在执行了SET ROLE admin之后才会拥有。

销毁一个组角色:

sql
1DROP ROLE name;

任何在该组角色中的成员关系会被自动撤销(但是成员角色不会受到影响)。

删除角色

由于角色可以拥有数据库对象并且能持有访问其他对象的特权,删除一个角色 常常并非一次DROP ROLE就能解决。

任何被该用户所拥有 的对象必须首先被删除或者转移给其他拥有者,并且任何已被授予给该角色的 权限必须被收回。

对象的拥有关系可以使用ALTER命令一次转移出去,例如:

sql
1ALTER TABLE bobs_table OWNER TO alice;